package com.yuexi.domain.payment.wxpay;

import com.alibaba.fastjson.JSON;
import com.github.binarywang.wxpay.bean.request.WxPayMicropayRequest;
import com.github.binarywang.wxpay.bean.request.WxPayOrderReverseRequest;
import com.github.binarywang.wxpay.bean.result.WxPayMicropayResult;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult;
import com.github.binarywang.wxpay.bean.result.WxPayOrderReverseResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.yuexi.domain.config.wxpay.WxPayProperties;
import com.yuexi.domain.payment.wxpay.bo.MicropayBO;
import com.yuexi.domain.payment.wxpay.definds.QueryOrderErrorCode;
import com.zenx.domain.Entity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.regex.Pattern;

/**
 * @author jie
 * @date 2023/4/6 -14:28
 */
@Slf4j
@Entity
public class WePayDomain {

    @Autowired
    private WxPayService wxService;
    @Autowired
    private WxPayProperties wxPayProperties;
    private String matchAuthCodeRegex = "^1[0-6][0-9]{16}$";

    /**
     * 验证authCode是否正确
     * 规则：（用户付款码规则：18位纯数字，前缀以10、11、12、13、14、15开头）
     */
    public boolean verifyAuthCode(String authCode) {
        return Pattern.matches(matchAuthCodeRegex, authCode);
    }

    /**
     * 付款码支付
     */
    public WxPayMicropayResult micropay(MicropayBO bo) throws WxPayException {
        WxPayMicropayRequest request = new WxPayMicropayRequest();
        // 传入的值
        request.setAuthCode(bo.getAuthCode());
        request.setOutTradeNo(bo.getOutTradeNo());
        request.setTotalFee(bo.getTotalFee());

        // 配置读取
        request.setSpbillCreateIp(wxPayProperties.getSpbillCreateIp());
        request.setBody(wxPayProperties.getBody());

        return wxService.micropay(request);
    }

    /**
     * 查询订单
     */
    public WxPayOrderQueryResult queryOrder(String outTradeNo) throws WxPayException {
        WxPayOrderQueryResult wxPayOrderQueryResult = wxService.queryOrder(null, outTradeNo);
        String jsonStr = JSON.toJSONString(wxPayOrderQueryResult);
        log.info("查询订单结果jsonStr：\n" + jsonStr + "\n");
        return wxPayOrderQueryResult;
    }

    /**
     * 撤销订单
     */
    public WxPayOrderReverseResult reverseOrder(String outTradeNo) throws WxPayException {
        WxPayOrderReverseRequest request = new WxPayOrderReverseRequest();
        request.setOutTradeNo(outTradeNo);
        return this.wxService.reverseOrder(request);
    }

    /**
     * 撤销订单，内部处理了异常消息
     */
    public void doReverseTry(String outTradeNo) {
        try {
            // 撤销订单
            this.reverseOrder(outTradeNo);
        } catch (WxPayException e) {
            if ("FAIL".equals(e.getReturnCode())) {
                throw new RuntimeException(e.getReturnMsg());
            } else {
                throw new RuntimeException(e.getErrCodeDes());
            }
        }
    }

    /**
     * 轮徇查询订单
     *
     * @param outTradeNo     外部订单号
     * @param attemptNumber 尝试次数
     */
    public boolean attemptQueryOrder(String outTradeNo, int attemptNumber) {

        for (int i = 0; i < attemptNumber; i++) {
            try {
                WxPayOrderQueryResult orderQueryResult = this.queryOrder(outTradeNo);
                if ("SUCCESS".equals(orderQueryResult.getReturnCode())
                        && "SUCCESS".equals(orderQueryResult.getResultCode())
                        && "SUCCESS".equals(orderQueryResult.getTradeState())) {

                    return true;
                } else {
                    // 如果交易状态是未知
                    if (QueryOrderErrorCode.isUnknownState(orderQueryResult.getTradeState())) {
                        Thread.sleep(10000);
                        continue;
                    } else {
                        throw new RuntimeException(orderQueryResult.getTradeStateDesc());
                    }
                }
            } catch (WxPayException e) {
                if ("FAIL".equals(e.getReturnCode())) {
                    throw new RuntimeException(e.getReturnMsg());
                } else {
                    throw new RuntimeException(e.getErrCodeDes());
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        return false;
    }
}
